package com.x52im.rainbowchat.http.logic.pay.alipay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.eva.framework.dbpool.DBShell;
import com.eva.framework.utils.LoggerFactory;
import com.x52im.rainbowchat.BaseConf;
import com.x52im.rainbowchat.http.logic.dto.AccountDTO;
import com.x52im.rainbowchat.http.logic.dto.AlipayDepositDTO;
import com.x52im.rainbowchat.http.logic.pay.redenvelope.GenSubEnvelope;

import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Map;
import java.util.Vector;

public class MDeposit {
    DBShell db = new DBShell();

    /**
     * 1、通过SDK获取发送给支付宝的订单信息字符串
     *
     * @param dto
     * @return
     * @throws Exception
     */
    public String getOrderStr(AlipayDepositDTO dto) throws Exception {
        dto.setSubject("红包主题");
        dto.setProductCode("红包");

        String yuan = GenSubEnvelope.fenToYuan(String.valueOf(dto.getTotalAmount()));

        String outTradeNo = AlipayClientTools.getOutTradeNo(String.valueOf(dto.getUserUid()));
        dto.setOutTradeNo(outTradeNo);

        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, 20);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timeExpire = simpleDateFormat.format(calendar.getTime());
        model.setTimeExpire(timeExpire);  // 20分钟后超时
        model.setOutTradeNo(outTradeNo);
        model.setSubject(dto.getSubject());
        model.setProductCode(dto.getProductCode());
        model.setTotalAmount(yuan);
        model.setBody(String.valueOf(dto.getUserUid()));
        request.setBizModel(model);
        request.setNotifyUrl(BaseConf.getInstance().getALI_DEPOSIT_REDIRECT_URL());
        AlipayTradeAppPayResponse response = AlipayClientTools.alipayClient.sdkExecute(request);

        String sql = "INSERT INTO alipay_deposit " +
                "(alipay_user_id, user_uid, out_trade_no, trade_no, total_amount, msg, code, subject, product_code, time_expire, create_date)" +
                "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?,  str_to_date('" + timeExpire + "','%Y-%m-%d %H:%i:%s'), now())";
        boolean b = db.update(sql, new Object[]{
                dto.getAlipayUserId(),
                dto.getUserUid(),
                dto.getOutTradeNo(),
                response.getTradeNo(),
                dto.getTotalAmount(),
                response.getMsg(),
                response.getCode(),
                dto.getSubject(),
                dto.getProductCode()}, true);

        return response.getBody();
    }

    /**
     * 2、前端发送第一步的字符串给支付宝后,支付宝返回订单信息
     *
     * @param dto
     * @return
     */
    public String getAliOrderInfo(AlipayDepositDTO dto) throws Exception {
        String _msg = dto.getMsg();
        JSONObject jsonObject = JSON.parseObject(_msg);
        JSONObject response1 = JSON.parseObject(jsonObject.getString("alipay_trade_app_pay_response"));

        String msg = response1.getString("msg");
        String code = response1.getString("code");
        String outTradeNo = response1.getString("out_trade_no");
        String sellerId = response1.getString("seller_id");
        String totalAmount = response1.getString("total_amount");
        String appId = response1.getString("app_id");

        // 查验 https://opendocs.alipay.com/open/00iki4
        String sql = "select total_amount from alipay_deposit where out_trade_no='" + outTradeNo + "'";
        String[] datas = db.querySingleRowItems(sql);
        // 1.商户需要验证该通知数据中的 out_trade_no 是否为商户系统中创建的订单号
        if (datas.length == 0) {

        }

        // 2.判断 total_amount 是否确实为该订单的实际金额（即商户订单创建时的金额）
        String _totalAmount = datas[0];
        if (!totalAmount.equals(_totalAmount)) {
            // TODO: 2022/5/29 元转分,以及精度
        }

        // 3.校验通知中的 seller_id（或者 seller_email) 是否为 out_trade_no 这笔单据对应的操作方（有的时候，一个商户可能有多个 seller_id/seller_email）
        if (!sellerId.equals(BaseConf.getInstance().getAPP_ALIPAY_USER_ID())) {
            // TODO: 2022/5/29
        }


        // 4.验证 app_id 是否为该商户本身(AlipayTradeAppPayResponse没有appId?....)
        // TODO: 2022/5/29

        if (true) {
            String sql1 = "UPDATE alipay_deposit SET sync_seller_id=?, sync_result_status=?, sync_memo=? WHERE out_trade_no=?";
            boolean b = db.update(sql1, new Object[]{sellerId, code, msg, outTradeNo}, true);
        }

        return "success";
    }

    /**
     * 3、第二步支付成功后,支付宝会调用MDepositRedirect异步通知支付结果
     *
     * @throws Exception
     */
    public boolean notifyBy(Map<String, String> params) throws Exception {
        Vector sqls = new Vector();
        Vector values = new Vector();

        String notify_time = params.get("notify_time");
        String notify_type = params.get("notify_type");
        String notify_id = params.get("notify_id");
        String auth_app_id = params.get("auth_app_id");
        String sign = params.get("sign");
        String trade_no = params.get("trade_no");
        String out_trade_no = params.get("out_trade_no");
        String out_biz_no = params.get("out_biz_no");
        String buyer_id = params.get("buyer_id");
        String buyer_logon_id = params.get("buyer_logon_id");
        String seller_id = params.get("seller_id");
        String seller_email = params.get("seller_email");
        String trade_status = params.get("trade_status");
        String total_amount = params.get("total_amount");
        String receipt_amount = params.get("receipt_amount");
        String invoice_amount = params.get("invoice_amount");
        String buyer_pay_amount = params.get("invoice_amount");
        String point_amount = params.get("invoice_amount");
        String refund_fee = params.get("invoice_amount");
        String subject = params.get("subject");
        String body = params.get("body");
        String gmt_create = params.get("gmt_create");
        String gmt_payment = params.get("gmt_payment");
        String gmt_refund = params.get("gmt_refund");
        String gmt_close = params.get("gmt_close");
        String fund_bill_list = params.get("fund_bill_list");

        Map<String, Object> data = db.queryDataMap("select id, user_uid from alipay_deposit where out_trade_no='" + out_trade_no + "'");
        JSONObject datajson = new JSONObject(data);
        String id = datajson.getString("id");
        String user_uid = datajson.getString("user_uid");

        // 插入日志表
        String sql1 = "INSERT INTO alipay_deposit_notify (" +
                "user_uid, notify_time,notify_type,notify_id," +
                "auth_app_id,sign,trade_no,out_trade_no,out_biz_no," +
                "buyer_id,buyer_logon_id,seller_id,seller_email," +
                "trade_status,total_amount,receipt_amount,invoice_amount,buyer_pay_amount,point_amount,refund_fee," +
                "subject,body,gmt_create,gmt_payment,gmt_refund,gmt_close,fund_bill_list)" +
                "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
        sqls.add(sql1);
        values.add(new Object[]{
                user_uid, notify_time, notify_type, notify_id,
                auth_app_id, sign, trade_no, out_trade_no, out_biz_no,
                buyer_id, buyer_logon_id, seller_id, seller_email,
                trade_status, total_amount, receipt_amount, invoice_amount, buyer_pay_amount, point_amount, refund_fee,
                subject, body, gmt_create, gmt_payment, gmt_refund, gmt_close, fund_bill_list
        });
        boolean a = db.update(sqls, values, true);
        if (a) {
            sqls.clear();
            values.clear();

            // 更新账户
            int totalNew = getTotlaNew(buyer_pay_amount, user_uid);
            String sql3 = "UPDATE missu_account SET total=?, alipay_user_id=? WHERE user_uid=?";
            sqls.add(sql3);
            values.add(new Object[]{totalNew, buyer_id, user_uid});

            // 插入账户历史表
            String fen = GenSubEnvelope.yuanTofen(buyer_pay_amount);
            sqls.add("INSERT INTO missu_account_his(user_uid,total,`type`,type_id,change_amount) VALUES(?,?,?,?,?)");
            values.add(new Object[]{user_uid, totalNew, AccountDTO.TYPE_FOR_DEPOSIT, id, fen});

            boolean b = db.update(sqls, values, true);
            LoggerFactory.getLog().info(String.format("充值回调完成,%s,%s,%s", user_uid, id, b));
            if (b) {
                return true;
            }
        }

        return false;
    }

    private int getTotlaNew(String buyer_pay_amount, String user_uid) throws Exception {
        String fen = GenSubEnvelope.yuanTofen(buyer_pay_amount);
        String _totalAmount = fen;
        int totalAmount = Integer.parseInt(_totalAmount);
        String _total = db.querySingleItem("total", "missu_account", "user_uid=" + user_uid);
        int total = Integer.parseInt(_total);
        int totlaNew = total + totalAmount;

        return totlaNew;
    }
}
